# -*- coding: utf-8 -*-

import os
import time
import json
import shutil
import socket
import struct
import xml.etree.ElementTree as ET
from os.path import join, dirname, realpath
from flask import Flask, render_template, request

app = Flask(__name__)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffsize = 1024
doc_dir_path = ''
csv_path = ''
global page
global keys
global doc_id


def init():
    global dir_path
    # s.connect(('10.46.30.126', 7778))
    # s.connect(('0.0.0.0', 7778))
    s.connect(('127.0.0.1', 7778))
    dir_path = join(dirname(realpath(__file__)), 'news/')


@app.route('/')
def main():
    init()
    return render_template('search.html', error=True)

# 读取表单数据，获得doc_ID
@app.route('/search_web/', methods=['POST'])
def search():
    try:
        global keys
        global page
        global checked
        global doc_id
        checked = ['checked="true"', '', '']
        keys = request.form['key_word']
        if keys not in ['']:
            s.send(keys.encode(encoding='utf-8'))  # 把句子传给server

            flag = s.recv(10).decode('utf-8')  # 表示状态的整型
            s.send('0'.encode(encoding='utf-8'))

            if flag == '0':
                return render_template('search.html', error=False)  # 搜索结果不存在的情况

            page = recv_page(s)  # 接收page，格式是list
            doc_id = recv_doc_id(s)  # 接收docid，格式是list
            recv_file(s)  # 收文件，储存在本地
            docs = cut_page(page, 0)

            return render_template('search.html', checked=checked, key=keys, docs=docs, page=page, error=True)
        else:
            return render_template('search.html', error=False)  # 键入为空的情况

    except Exception as e:
        print('search error:%s' % str(e))


@app.route('/search/page/<page_no>/', methods=['GET'])
def next_page(page_no):
    global page
    try:
        page_no = int(page_no)
        docs = cut_page(page, (page_no - 1))
        return render_template('search.html', checked=checked, key=keys, docs=docs, page=page,
                               error=True)
    except:
        print('next error')


@app.route('/search/<id>/', methods=['GET', 'POST'])
def content(id):
    try:
        doc = find([id], extra=True)
        return render_template('content.html', doc=doc[0])
    except:
        print('content error')


def cut_page(page, no):
    docs = find(doc_id[no * 10:page[no] * 10])
    return docs


# 将需要的数据以字典形式打包传递给search函数
def find(docid, extra=False):
    docs = []
    global dir_path
    for id in docid:
        root = ET.parse(dir_path + '%s.xml' % id).getroot()
        url = root.find('url').text
        title = root.find('title').text
        body = root.find('body').text
        snippet = root.find('body').text[0:120] + '……'
        time = root.find('datetime').text.split(' ')[0]
        datetime = root.find('datetime').text
        doc = {'url': url, 'title': title,
               'snippet': snippet, 'datetime': datetime,
               'time': time, 'body': body,
               'id': id}
        docs.append(doc)
    print('find done!')
    return docs


def recv_doc_id(socket):
    doc_id_len = int(socket.recv(1024).decode('utf-8'))  # 接收报头,docid的长度
    socket.send('0'.encode(encoding='utf-8'))
    recv_len = 0
    doc_id_json = b''
    while recv_len < doc_id_len:
        if doc_id_len - recv_len > buffsize:
            recv_mesg = socket.recv(buffsize)
            doc_id_json += recv_mesg
            recv_len += len(recv_mesg)
        else:
            recv_mesg = socket.recv(doc_id_len - recv_len)
            doc_id_json += recv_mesg
            recv_len += len(recv_mesg)

    socket.send('0'.encode(encoding='utf-8'))
    doc_id = json.loads(doc_id_json)  # 储存doc_id的list

    return doc_id


def recv_page(socket):
    page_json = socket.recv(2048).decode('utf-8')
    page = json.loads(page_json)  # 从1开始的list，储存页码
    socket.send('0'.encode(encoding='utf-8'))
    return page


def recv_file(socket):
    try:
        shutil.rmtree('news')
        os.mkdir('news')
    except Exception as e:
        print(str(e))
    length = socket.recv(1024).decode('utf-8')  # 接收文件数目
    socket.send('0'.encode(encoding='utf-8'))

    for i in range(int(length)):
        head_struct = socket.recv(4)  # 接收报头长度
        socket.send('0'.encode(encoding='utf-8'))

        if head_struct:
            print('已连接服务端,等待接收文件')
        head_len = struct.unpack('i', head_struct)[0]  # 解析出报头的字符串大小

        data = socket.recv(head_len)  # 接收长度为head_len的报头内容的信息 (包含文件大小,文件名的内容)
        socket.send('0'.encode(encoding='utf-8'))

        head_dir = json.loads(data.decode('utf-8'))
        filesize_b = head_dir['filesize_bytes']
        filename = head_dir['filename']

        #   接受真的文件内容
        recv_len = 0
        recv_mesg = b''
        old = time.time()
        f = open('news/' + filename, 'wb')
        while recv_len < filesize_b:
            if filesize_b - recv_len > buffsize:
                recv_mesg = socket.recv(buffsize)
                f.write(recv_mesg)
                recv_len += len(recv_mesg)
            else:
                recv_mesg = socket.recv(filesize_b - recv_len)
                recv_len += len(recv_mesg)
                f.write(recv_mesg)

        print("Receive Bytes：" + str(recv_len) + 'bytes')
        print("File size：" + str(filesize_b) + 'bytes')
        now = time.time()
        stamp = (now - old) * 1000
        print('总共用时:%fms' % stamp)
        f.close()
        time.sleep(0.1)


if __name__ == '__main__':
    app.run(debug=True, host='127.0.0.1', port=7877)
